﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace BTM_Client_Application.RealTimeFilter
{
    class DataGridAutoInitFilter<T> where T : IRealTimeFilterObject
    {
        //public ObservableCollection<DataGridRow> FilteredItems { get; private set; }
        public ObservableCollection<T> FilteredItems { get; private set; }
        readonly ObservableCollection<T> _allItems;
        public RealTimeFilterControl FilterControl { get; private set; }
        private readonly Dictionary<string, FilterElementControl> _filters; 

        private DataGridAutoInitFilter(Orientation orientation = Orientation.Horizontal)
        {
            //FilteredItems = new ObservableCollection<DataGridRow>();
            FilteredItems = new ObservableCollection<T>();
            FilterControl = new RealTimeFilterControl {ElementsPanel = {Orientation = orientation}};
            _filters = new Dictionary<string, FilterElementControl>();
        }

        public DataGridAutoInitFilter(T initItem, ref ObservableCollection<T> allItems,
                                      out List<DataGridColumn> dataGridColumns,
                                      Orientation orientation = Orientation.Horizontal)
            : this(orientation)
        {
            _allItems = allItems;
            dataGridColumns = new List<DataGridColumn>(initItem.FilterInterface.Count);
            foreach (var fint in initItem.FilterInterface)
            {
                
                var ci = fint.Value.ColumnInitializer;
                if (ci == null)
                    continue;
                //var c = new DataGridTextColumn {Header = fint.Key, Binding = new Binding(fint.Key)};
                var c = new DataGridTextColumn(){Header = ci.Header, Binding = new Binding(ci.Binding)};
                if (fint.Value.ElementType == FilterElementType.StartAndEndTime ||
                    fint.Value.ElementType == FilterElementType.StartTime ||
                    fint.Value.ElementType == FilterElementType.EndTime)
                {
                    c.Binding.StringFormat = "dd/MM/yyyy HH:mm";
                }
                if (ci.Width != null)
                    c.Width = (int)ci.Width;
                
                dataGridColumns.Add(c);
            }
            foreach (var elementType in initItem.FilterInterface)
            {
                var filter = new FilterElementControl(elementType.Key, elementType.Value, On_UpdatedFilter);
                _filters.Add(elementType.Key, filter);
                //ElementsPanel.Children.Add(filter);
                if(elementType.Value.ElementType != FilterElementType.NoControl)
                    FilterControl.AddFilterElement(filter);
            }
        }

        public void ClearFilter()
        {
            foreach (var filter in _filters)
            {
                filter.Value.ClearFilter();
            }
        }

        public void On_NewError(T record)
        {
            if (CheckElement(record))
            {
                //FilteredItems.Add(new DataGridRow { Item = record });
                FilteredItems.Add(record);
            }
        }

        public void On_RemoveError(T record)
        {
            //var ier = FilteredItems.Single(x => Equals(x.Item, record));
            var ier = FilteredItems.Single(x => Equals(x, record));
            FilteredItems.Remove(ier);
            //var r = FilteredItems.Single(x => x.GetRecordId() == record.GetRecordId());
            //FilteredItems.Remove(r);
        }

        public void On_UpdatedFilter(FilterElementControl updatedFilter)
        {
            //FilteredItems.Clear();
            FilteredItems.Clear();
            foreach (var error in _allItems)
            {
                if (CheckElement(error))
                {
                    
                    FilteredItems.Add(error);
                    
                    //FilteredItems.Add(new DataGridRow { Item = error });
                }
            }
        }

        public void SetFilterActiveValues(string filterKey, FilterElementType valuesType,  List<object> values)
        {
            if(_filters.ContainsKey(filterKey))
                _filters[filterKey].SetFilterActiveValue(valuesType, values);
        }

        public bool CheckElement(IRealTimeFilterObject elementToCheck)
        {
            bool ckd = true;
            foreach (var element in elementToCheck.FilterElements)
            {
                if (_filters[element.Key] == null)
                    continue;
                if (!_filters[element.Key].CheckElement(element.Value))
                {
                    ckd = false;
                    break;
                }
            }
            return ckd;
        }

        public Dictionary<string, List<object>> GetRequestValues()
        {
            var dict = new Dictionary<string, List<object>>(_filters.Count);

            foreach (var filter in _filters)
            {
                dict.Add(filter.Key,new List<object>(filter.Value.ForRequestString));
            }

            return dict;
        }
    }
}
